#include <iostream>
#include "../CImg/CImg.h"
using namespace std;
using namespace cimg_library;


unsigned halftone_patterns[10][3][3]={
	{{0,0,0}, {0,0,0}, {0,0,0}},
	{{0,1,0}, {0,0,0}, {0,0,0}},
	{{0,1,0}, {0,0,0}, {0,0,1}},
	{{1,1,0}, {0,0,0}, {0,0,1}},
	{{1,1,0}, {0,0,0}, {1,0,1}},
	{{1,1,1}, {0,0,0}, {1,0,1}},
	{{1,1,1}, {0,0,1}, {1,0,1}},
	{{1,1,1}, {0,0,1}, {1,1,1}},
	{{1,1,1}, {1,0,1}, {1,1,1}},
	{{1,1,1}, {1,1,1}, {1,1,1}}
};

CImg<unsigned char> MakeHalftoneImage(CImg<unsigned char> img){
	CImg<unsigned char> halftone(img.width()*3, img.height()*3); // ??? ojo aca... Especificar nro de canales?
	CImg<unsigned char> copia=img; // para no romper la original
	copia.quantize(10, false); // cuantizamos la imagen para que tenga 10 niveles
	
	// recorre cada pixel de la imagen
	for(unsigned i=0; i<img.width(); i++){
		for(unsigned j=0; j<img.height(); j++){
			// recorre los 9 puntos del patron
			for(unsigned k=0; k<3; k++){
				for(unsigned l=0; l<3; l++){
					// aplicamos el patron segun la intensidad de la copia cuantizada
					halftone(i*3+k, j*3+l)=halftone_patterns[copia(i,j)][k][l]*255; // el 255 es xq usamos false en quantize para tener los niveles desde 0
				}
			}
		}
	}
	return halftone;
}	

// genera un degrade de intensidad del tamanio dado
CImg<unsigned char> GeneraDegrade(unsigned w, unsigned h, bool vertical=true){
	CImg<unsigned char> degrade(w, h); 
	for(unsigned i=0; i<w; i++){
		for(unsigned j=0; j<h; j++){
			if(vertical){
				degrade(i, j)=(unsigned char)((float(i)/h)*255);
			}else{
				degrade(i, j)=(unsigned char)((float(j)/w)*255);
			}
		}
	}
	return degrade;
}

int main(int argc, char *argv[]) {
	CImg<unsigned char> imgOrig, halftone; 
	CImgDisplay displayOrig, displayHalftone, displayHalftoneResized, displayDegrade;
	
	
	
	imgOrig.load("../img_test/huang3.jpg");
	halftone=MakeHalftoneImage(imgOrig);
	halftone.save_bmp("huang3_halftone.bmp");
	displayOrig.assign(imgOrig);
	displayHalftone.assign(halftone);
	halftone.resize(halftone.width()/3, halftone.height()/3);
	displayHalftoneResized.assign(halftone);
	displayDegrade.assign(MakeHalftoneImage(GeneraDegrade(200,200)));

	
	while(!displayOrig.is_closed() && !displayHalftone.is_closed() && !displayHalftoneResized.is_closed()){
		displayOrig.wait_all();
		
	}
	
	/// CONCLUSIONES
	// En el degrade se obtienen niveles de intensidad conformados por ptos blancos y negros, pero solo 10 niveles
	// ya que para representarla de esta forma es necesario cuantizar la imagen
	
	// las demas imagenes pueden ser representadas por matrices de puntos pero es necesario aumentar su
	// resolucion (triplicar). Se consiguen buenos resultados. Al volver a la imagen al tamanio original, por cada
	// cuadrado de 3x3 pixeles se toma un pixel (el predominante, sea blanco o negro) asi la imagen queda como una
	// imagen monocromo
	
	
	
	return 0;
}


